﻿using System;
using System.Collections;
using System.Collections.Generic;
using OWL.Rendering.HRP;
using UnityEngine;
using UnityEngine.AI;
using Yoozoo.HRP.Runtime;

public class NavMeshBakeHelper : MonoBehaviour
{
    public float x;
    public float y;
    public float z;
    
    private static NavMeshData m_navMesh;
    
    private static NavMeshDataInstance m_navMeshInstance;
    
    public static NavMeshData navMesh
    {
        get
        {
            if (m_navMesh == null)
            {
                m_navMesh = new NavMeshData();
                m_navMeshInstance = NavMesh.AddNavMeshData(m_navMesh);
            }
            return m_navMesh;
        }
    }

    public static NavMeshBakeHelper Instance
    {
        get
        {
            var obj = FindObjectOfType<NavMeshBakeHelper>();
            return obj;
        }
    }
    
    private static HashSet<string> m_filterNameSet = new HashSet<string>()
    {
        "traffic_light",
        "traffic_light (1)",
    };

    private static HashSet<string> m_filterNameContainsSet = new HashSet<string>()
    {
        "rpg_road_decal_water",
    };

    public static void BakeNavMesh(Transform root = null)
    {
#if UNITY_EDITOR
        UnityEngine.AssetStandardProcessors.AssetGraphPostprocessor.Postprocessor.Enabled = false;
        UnityEngine.AssetStandardProcessors.AssetGraphPostprocessor.Postprocessor.Log = false;
#endif
        List<NavMeshBuildSource> sourceList = new List<NavMeshBuildSource>();
        MeshFilter[] meshes;
        Vector3 center = Vector3.zero;
        float x = 100;
        float y = 50;
        float z = 100;
        if (Instance != null)
        {
            center = Instance.transform.position;
            x = Instance.x;
            y = Instance.y;
            z = Instance.z;
        }
        if (root == null)
        {
            meshes = GameObject.FindObjectsOfType<MeshFilter>();
        }
        else
        {
            meshes = root.GetComponentsInChildren<MeshFilter>();
        }
        for (int i = 0; i < meshes.Length; i++)
        {
            var meshFilter = meshes[i];
            if (m_filterNameSet.Contains(meshFilter.name))
            {
                continue;
            }

            var containsFilter = false;
            foreach (var item in m_filterNameContainsSet)
            {
                if (meshFilter.name.Contains(item))
                {
                    containsFilter = true;
                    break;
                }
            }

            if (containsFilter)
            {
                continue;
            }
            if (meshFilter.gameObject.activeInHierarchy && meshFilter.sharedMesh != null)
            {
                if (!meshFilter.sharedMesh.isReadable)
                {
                    //BattleDebug.LogError(meshes[i].sharedMesh.name);
#if UNITY_EDITOR
                    BattleDebug.LogError("试图把"+meshes[i].sharedMesh.name+"变为可读");
                    SetMeshReadable(meshFilter.sharedMesh);
                    BattleDebug.LogError(meshes[i].sharedMesh.name+" 的可读性为 "+meshFilter.sharedMesh.isReadable);
                    sourceList.Add(new NavMeshBuildSource
                    {
                        shape = NavMeshBuildSourceShape.Mesh,
                        area = 0,
                        transform = meshFilter.transform.localToWorldMatrix,
                        sourceObject = meshFilter.sharedMesh,
                        component = meshFilter
                    });
#endif
                }
                else
                {
                    sourceList.Add(new NavMeshBuildSource
                    {
                        shape = NavMeshBuildSourceShape.Mesh,
                        area = 0,
                        transform = meshFilter.transform.localToWorldMatrix,
                        sourceObject = meshFilter.sharedMesh,
                        component = meshFilter
                    });
                }
            }
        }
        var defaultBuildSettings = NavMesh.GetSettingsByID(NavMesh.GetSettingsByIndex(2).agentTypeID);
        var bounds = new Bounds(center, new Vector3(x,y,z));
        var result = NavMeshBuilder.UpdateNavMeshData(navMesh, defaultBuildSettings, sourceList, bounds);
        if (result)
        {
            BattleDebug.LogError("烘焙成功 " + sourceList.Count);
        }
        else
        {
            BattleDebug.LogError("烘焙失败");
        }
#if UNITY_EDITOR
        UnityEngine.AssetStandardProcessors.AssetGraphPostprocessor.Postprocessor.Enabled = true;
        UnityEngine.AssetStandardProcessors.AssetGraphPostprocessor.Postprocessor.Log = true;
#endif
    }

    public static void CollectSource()
    {
        var sources = new List<NavMeshBuildSource>();
        var markups = new List<NavMeshBuildMarkup>();
        NavMeshBuilder.CollectSources(null, 0, NavMeshCollectGeometry.RenderMeshes, NavMesh.AllAreas, markups, sources);
        BattleDebug.LogError(sources.Count + " " + markups.Count);
        for (int i = 0; i < markups.Count; i++)
        {
            BattleDebug.LogError(markups[i].root.name);
        }
        for (int i = 0; i < sources.Count; i++)
        {
            BattleDebug.LogError(sources[i].shape);
            BattleDebug.LogError(sources[i].component.name);
        }
    }
    
    public static GameObject CreateMeshObject()  
    {
        NavMeshTriangulation triangulatedNavMesh = NavMesh.CalculateTriangulation();
        var prefab = new GameObject("prefab");
        var meshFilterCombine = prefab.AddComponent<MeshFilter>();
        Mesh mesh = new Mesh();
        mesh.name = "_NavMesh";
        mesh.vertices = triangulatedNavMesh.vertices;
        mesh.triangles = triangulatedNavMesh.indices;
        meshFilterCombine.mesh = mesh;
        BattleDebug.LogError(triangulatedNavMesh.areas.Length + " " + triangulatedNavMesh.indices.Length + " " + triangulatedNavMesh.vertices.Length);
        BattleDebug.LogError(mesh.vertices.Length);
        BattleDebug.LogError(mesh.triangles.Length);
        return prefab;
    }

    private void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireCube(transform.position, new Vector3(x,y,z));
    }

    public static void Clear()
    {
        NavMesh.RemoveNavMeshData(m_navMeshInstance);
        m_navMesh = null;
    }

    private static void SetMeshReadable(Mesh mesh)
    {
#if UNITY_EDITOR
        string fbxPath = UnityEditor.AssetDatabase.GetAssetPath(mesh);

        UnityEditor.ModelImporter mImporter = UnityEditor.AssetImporter.GetAtPath(fbxPath) as UnityEditor.ModelImporter;
        if (mImporter)
        {
            if (!mImporter.isReadable)
            {
                mImporter.isReadable = true;
                mImporter.SaveAndReimport();
            }
        }
#endif
    }
}
